package com.jprocms.module.cms.service.accesslog;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.page.PageMethod;
import com.jprocms.module.cms.dal.dataobject.accesslog.AccessLogDO;
import com.jprocms.module.cms.dal.dataobject.accesspage.AccessPageDO;
import com.jprocms.module.cms.dal.dataobject.accessstatistics.AccessStatisticsDO;
import com.jprocms.module.cms.dal.dataobject.accesstrend.AccessTrendDO;
import com.jprocms.module.cms.dal.mysql.accesslog.AccessLogMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.OffsetDateTime;
import java.util.List;

import static com.jprocms.module.cms.dal.dataobject.accessstatistics.AccessStatisticsDO.STAT_MAX_SIZE;

/**
 * 访问日志 Service 实现类
 *
 * @author jprocms
 */
@Service
@Validated
public class AccessLogServiceImpl extends ServiceImpl<AccessLogMapper, AccessLogDO> implements AccessLogService {

    @Resource
    private AccessLogMapper accessLogMapper;

    /**
     * 统计访客数
     *
     * @param date   在此日期后
     * @param siteId
     * @return 访客数
     */
    public int countVisitors(OffsetDateTime date, Long siteId) {
        return accessLogMapper.countVisitors(date, siteId);
    }

    public List<AccessStatisticsDO> statByType(Integer type, OffsetDateTime begin, OffsetDateTime end) {
        switch (type) {
            case AccessStatisticsDO.TYPE_VISITOR:
                return statVisitor(begin, end);
            case AccessStatisticsDO.TYPE_SOURCE:
                return statSource(begin, end);
            case AccessStatisticsDO.TYPE_COUNTRY:
                return statCountry(begin, end);
            case AccessStatisticsDO.TYPE_PROVINCE:
                return statProvince(begin, end);
            case AccessStatisticsDO.TYPE_DEVICE:
                return statDevice(begin, end);
            case AccessStatisticsDO.TYPE_OS:
                return statOs(begin, end);
            case AccessStatisticsDO.TYPE_BROWSER:
                return statBrowser(begin, end);
            case AccessStatisticsDO.TYPE_SOURCE_TYPE:
                return statSourceType(begin, end);
            default:
                throw new IllegalArgumentException("Unsupported type: " + type);
        }
    }

    /**
     * 统计新老访客
     *
     * @param begin 开始日期
     * @param end   介绍日期
     * @return 统计结果
     */
    public List<AccessStatisticsDO> statVisitor(OffsetDateTime begin, OffsetDateTime end) {
        return PageMethod.offsetPage(0, STAT_MAX_SIZE, false).doSelectPage(
                () -> accessLogMapper.statByName("new_visitor", begin, end));
    }

    /**
     * 统计来源
     *
     * @param begin 开始日期
     * @param end   介绍日期
     * @return 统计结果
     */
    public List<AccessStatisticsDO> statSource(OffsetDateTime begin, OffsetDateTime end) {
        return PageMethod.offsetPage(0, STAT_MAX_SIZE, false).doSelectPage(
                () -> accessLogMapper.statByName("access_source", begin, end));
    }

    /**
     * 统计来源分类
     *
     * @param begin 开始日期
     * @param end   介绍日期
     * @return 统计结果
     */
    public List<AccessStatisticsDO> statSourceType(OffsetDateTime begin, OffsetDateTime end) {
        return PageMethod.offsetPage(0, STAT_MAX_SIZE, false).doSelectPage(
                () -> accessLogMapper.statByName("source_type", begin, end));
    }

    /**
     * 统计国家
     *
     * @param begin 开始日期
     * @param end   介绍日期
     * @return 统计结果
     */
    public List<AccessStatisticsDO> statCountry(OffsetDateTime begin, OffsetDateTime end) {
        return PageMethod.offsetPage(0, STAT_MAX_SIZE, false).doSelectPage(
                () -> accessLogMapper.statByName("access_country", begin, end));
    }

    /**
     * 统计省份
     *
     * @param begin 开始日期
     * @param end   介绍日期
     * @return 统计结果
     */
    public List<AccessStatisticsDO> statProvince(OffsetDateTime begin, OffsetDateTime end) {
        String country = "中国";
        return PageMethod.offsetPage(0, STAT_MAX_SIZE, false).doSelectPage(
                () -> accessLogMapper.statProvince(country, begin, end));
    }

    /**
     * 统计设备
     *
     * @param begin 开始日期
     * @param end   介绍日期
     * @return 统计结果
     */
    public List<AccessStatisticsDO> statDevice(OffsetDateTime begin, OffsetDateTime end) {
        return PageMethod.offsetPage(0, STAT_MAX_SIZE, false).doSelectPage(
                () -> accessLogMapper.statByName("access_device", begin, end));
    }

    /**
     * 统计操作系统
     *
     * @param begin 开始日期
     * @param end   介绍日期
     * @return 统计结果
     */
    public List<AccessStatisticsDO> statOs(OffsetDateTime begin, OffsetDateTime end) {
        return PageMethod.offsetPage(0, STAT_MAX_SIZE, false).doSelectPage(
                () -> accessLogMapper.statByName("access_os", begin, end));
    }

    /**
     * 统计浏览器
     *
     * @param begin 开始日期
     * @param end   介绍日期
     * @return 统计结果
     */
    public List<AccessStatisticsDO> statBrowser(OffsetDateTime begin, OffsetDateTime end) {
        return PageMethod.offsetPage(0, STAT_MAX_SIZE, false).doSelectPage(
                () -> accessLogMapper.statByName("access_browser", begin, end));
    }

    /**
     * 统计受访页面
     *
     * @param begin 开始日期
     * @param end   介绍日期
     * @return 统计结果
     */
    public List<AccessPageDO> statUrl(OffsetDateTime begin, OffsetDateTime end) {
        return PageMethod.offsetPage(0, STAT_MAX_SIZE, false).doSelectPage(
                () -> accessLogMapper.statUrl(begin, end));
    }

    /**
     * 统计入口页面
     *
     * @param begin 开始日期
     * @param end   介绍日期
     * @return 统计结果
     */
    public List<AccessPageDO> statEntryUrl(OffsetDateTime begin, OffsetDateTime end) {
        return PageMethod.offsetPage(0, STAT_MAX_SIZE, false).doSelectPage(
                () -> accessLogMapper.statEntryUrl(begin, end));
    }

    /**
     * 统计趋势
     *
     * @param begin 开始日期
     * @param end   介绍日期
     * @return 统计结果
     */
    public List<AccessTrendDO> statTrend(OffsetDateTime begin, OffsetDateTime end) {
        return accessLogMapper.statTrend(begin, end);
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteBeforeDate(OffsetDateTime date) {
        accessLogMapper.deleteBeforeDate(date);
    }

    //TOOD 站点删除需要删除访问日志

}
